function mxGraphSelectionModel(graph)
{
	this.graph = graph;
	this.cells = [];
};
mxGraphSelectionModel.prototype = new mxEventSource();
mxGraphSelectionModel.prototype.constructor = mxGraphSelectionModel;
mxGraphSelectionModel.prototype.doneResource = (mxClient.language != 'none') ? 'done' : '';
mxGraphSelectionModel.prototype.updatingSelectionResource = (mxClient.language != 'none') ? 'updatingSelection' : '';
mxGraphSelectionModel.prototype.graph = null;
mxGraphSelectionModel.prototype.singleSelection = false;
mxGraphSelectionModel.prototype.isSingleSelection = function()
{
	return this.singleSelection;
};
mxGraphSelectionModel.prototype.setSingleSelection = function(singleSelection)
{
	this.singleSelection = singleSelection;
};
mxGraphSelectionModel.prototype.isSelected = function(cell)
{
	if (cell != null)
	{
		var state = this.graph.getView().getState(cell);
		return this.graph.hasHandler(state);
	}
	return false;
};
mxGraphSelectionModel.prototype.isEmpty = function()
{
	return this.cells.length == 0;
};
mxGraphSelectionModel.prototype.clear = function()
{
	this.changeSelection(null, this.cells);
};
mxGraphSelectionModel.prototype.setCell = function(cell)
{
	if (cell != null)
	{
		this.setCells([cell]);
	}
};
mxGraphSelectionModel.prototype.setCells = function(cells)
{
	if (cells != null)
	{
		if (this.singleSelection)
		{
			cells = [this.getFirstSelectableCell(cells)];
		}
		var tmp = [];

		for (var i = 0; i < cells.length; i++)
		{
			if (this.graph.isCellSelectable(cells[i]))
			{
				tmp.push(cells[i]);
			}
		}
		this.changeSelection(tmp, this.cells);
	}
};
mxGraphSelectionModel.prototype.getFirstSelectableCell = function(cells)
{
	if (cells != null)
	{
		for (var i = 0; i < cells.length; i++)
		{
			if (this.graph.isCellSelectable(cells[i]))
			{
				return cells[i];
			}
		}
	}
	return null;
};
mxGraphSelectionModel.prototype.addCell = function(cell)
{
	if (cell != null)
	{
		this.addCells([cell]);
	}
};
mxGraphSelectionModel.prototype.addCells = function(cells)
{
	if (cells != null)
	{
		var remove = null;

		if (this.singleSelection)
		{
			remove = this.cells;
			cells = [this.getFirstSelectableCell(cells)];
		}
		var tmp = [];

		for (var i = 0; i < cells.length; i++)
		{
			if (!this.isSelected(cells[i]) && this.graph.isCellSelectable(cells[i]))
			{
				tmp.push(cells[i]);
			}
		}
		this.changeSelection(tmp, remove);
	}
};
mxGraphSelectionModel.prototype.removeCell = function(cell)
{
	if (cell != null)
	{
		this.removeCells([cell]);
	}
};
mxGraphSelectionModel.prototype.removeCells = function(cells)
{
	if (cells != null)
	{
		var tmp = [];

		for (var i = 0; i < cells.length; i++)
		{
			if (this.isSelected(cells[i]))
			{
				tmp.push(cells[i]);
			}
		}
		this.changeSelection(null, tmp);
	}
};
mxGraphSelectionModel.prototype.changeSelection = function(added, removed)
{
	if ((added != null && added.length > 0 && added[0] != null)
		|| (removed != null && removed.length > 0 && removed[0] != null))
	{
		var change = new mxSelectionChange(this, added, removed);
		change.execute();
		var edit = new mxUndoableEdit(this, false);
		edit.add(change);
		this.fireEvent(mxEvent.UNDO, new mxEventObject([edit]));
	}
};
mxGraphSelectionModel.prototype.cellAdded = function(cell)
{
	if (cell != null)
	{
		var state = this.graph.getView().getState(cell);

		if (!this.graph.hasHandler(state))
		{
			this.graph.createHandler(state);
			this.cells.push(cell);
		}
	}
};
mxGraphSelectionModel.prototype.cellRemoved = function(cell)
{
	if (cell != null)
	{
		var index = mxUtils.indexOf(this.cells, cell);

		if (index >= 0)
		{
			var state = this.graph.getView().getState(cell);
			this.graph.destroyHandler(state);
			this.cells.splice(index, 1);
		}
	}
};
function mxSelectionChange(selectionModel, added, removed)
{
	this.selectionModel = selectionModel;
	this.added = (added != null) ? added.slice() : null;
	this.removed = (removed != null) ? removed.slice() : null;
};
mxSelectionChange.prototype.execute = function()
{
	var t0 = mxLog.enter('mxSelectionChange.execute');
	window.status = mxResources.get(this.selectionModel.updatingSelectionResource)
		|| this.selectionModel.updatingSelectionResource;

	if (this.removed != null)
	{
		for (var i = 0; i < this.removed.length; i++)
		{
			this.selectionModel.cellRemoved(this.removed[i]);
		}
	}

	if (this.added != null)
	{
		for (var i = 0; i < this.added.length; i++)
		{
			this.selectionModel.cellAdded(this.added[i]);
		}
	}
	var tmp = this.added;
	this.added = this.removed;
	this.removed = tmp;
	window.status = mxResources.get(this.selectionModel.doneResource) || this.selectionModel.doneResource;
	mxLog.leave('mxSelectionChange.execute', t0);
	this.selectionModel.fireEvent(mxEvent.CHANGE, new mxEventObject([this.removed, this.added]));
};